import events from "events";
import { checkOptions } from "@/utils/common/index";
import { MapEventController } from "@/utils/MapEventController";
export class LayerController extends events.EventEmitter {
  private map: any;
  private _layers: any = {};
  private mapEventController: any;

  constructor(options: any) {
    super();
    this.initOptions(options);
  }

  /**
   * 获取layers记录
   */
  public get layers() {
    return this._layers;
  }

  private initOptions(options: { map: any }) {
    const checkedOptions = checkOptions(options, [
      {
        key: "map",
        require: true,
      },
    ]);
    this.map = checkedOptions.map;
    this.mapEventController = new MapEventController(options);
  }

  /**
   * 移除全部图层
   */
  public removeAllLayers() {
    // 移除所有图层
    Object.entries(this._layers).forEach(([id, layer]) => {
      this.map.getLayer(id) && this.map.removeLayer(id);
    });

    // 清空记录
    this._layers = {};
  }

  /**
   * 显示所有图层
   */
  public showAllLayers() {
    Object.entries(this._layers).forEach(([id, layer]) => {
      this.map.getLayer(id) &&
        this.map.setLayoutProperty(id, "visibility", "visible");
    });
  }

  /**
   * 隐藏所有图层
   */
  public hideAllLayers() {
    Object.entries(this._layers).forEach(([id, layer]) => {
      this.map.getLayer(id) &&
        this.map.setLayoutProperty(id, "visibility", "none");
    });
  }

  /**
   * 显示图层
   * @param {string[]} layerIds 图层ID集合
   */
  public showLayers(layerIds: any) {
    if (Array.isArray(layerIds) && layerIds.length > 0) {
      layerIds.forEach((id) => {
        this.map.getLayer(id) &&
          this.map.setLayoutProperty(id, "visibility", "visible");
      });
    } else {
      this.showAllLayers();
    }
  }

  /**
   * 隐藏图层
   * @param {string[]} layerIds 图层ID集合
   */
  public hideLayers(layerIds: string[]) {
    if (Array.isArray(layerIds) && layerIds.length > 0) {
      layerIds.forEach((id) => {
        this.map.getLayer(id) &&
          this.map.setLayoutProperty(id, "visibility", "none");
      });
    } else {
      this.hideAllLayers();
    }
  }

  /**
   * 抛出错误
   * @param 错误路径
   * @param 错误描述
   */
  private __throwError__(path: string, description: string) {
    const errorInfo = {
      msg: `${path}:${description}`,
    };
    throw new Error(JSON.stringify(errorInfo));
  }

  /**
   * 添加图层
   * @param layer 图层数据
   * @param beforeId 前缀ID
   */
  public addLayer(layer: any, beforeId?: string) {
    if (this._layers[layer.id]) {
      console.warn(`图层${layer.id}已存在，正在尝试删除重复图层`);
      this.removeLayers([layer.id]);
      if (!this._layers[layer.id]) {
        console.info(`图层${layer.id}删除成功`);
      } else {
        throw new Error("删除重复图层失败，不能添加相同id的图层");
      }
    }
    try {
      this.map.addLayer(layer, beforeId);
      this._layers[layer.id] = layer;
      this.emit("successAddLayer", "success");
    } catch (error) {
      console.error("图层添加失败");
      this.emit("commonError", error);
    }
  }

  /**
   * 移除图层
   * @param {string[]} layerIds  图层Id集合
   */
  public removeLayers(layerIds: string[]) {
    if (Array.isArray(layerIds) && layerIds.length > 0) {
      // 按照传入layerIds移除图层
      layerIds.forEach((layerId) => {
        if (this.map.getLayer(layerId) && this._layers[layerId]) {
          this.map.removeLayer(this._layers[layerId].id);
          delete this._layers[layerId];
        } else {
          this.__throwError__(
            "layerController=>removeLayers",
            `${layerId}图层不存在`
          );
        }
      });
    } else {
      // 移除所有图层
      this.removeAllLayers();
    }
  }

  /**
   * 添加单个图层事件
   * @param {object} mapEvent 事件列表
   * @param {string} mapEvent.type 事件类型
   * @param {string} mapEvent.layerId 事件图层ID
   * @param {Function} mapEvent.listener 事件监听函数
   */
  public addLayerEvent(mapEvent: {
    type: string;
    layerId?: string;
    listener: any;
  }): void {
    try {
      this.mapEventController.registerMapEvent(mapEvent);
      this.emit("addLayerEvent", mapEvent);
    } catch (error) {
      if (error instanceof Error) {
        const errorMsg: string = error.message;
        this.__throwError__("LayerController=>addLayerEvent", errorMsg);
      } else {
        console.error("An unknown error occurred");
      }
    }
  }

  /**
   * @param {object} mapEvent 事件列表
   * @param {string} mapEvent.type 事件类型
   * @param {string} mapEvent.layerId 图层Id
   */
  public removeLayerEvent(mapEvent: { type: string; layerId?: string }) {
    try {
      this.mapEventController.removeMapEvent(mapEvent.type, mapEvent.layerId);
      this.emit("removeLayerEvent", mapEvent);
    } catch (error) {
      if (error instanceof Error) {
        const errorMsg: string = error.message;
        this.__throwError__("LayerController=>removeLayerEvent", errorMsg);
      } else {
        console.error("An unknown error occurred");
      }
    }
  }

  /**
   * 清空指定类型的地图事件
   * @param {object} mapEvent 事件列表
   * @param {string} mapEvent.type 事件类型
   */
  public clearLayerEvent(mapEvent: { type: string; layerId?: string }) {
    try {
      if (mapEvent.layerId) {
        this.mapEventController.clearMapEvent(mapEvent.type, mapEvent.layerId);
      } else {
        this.mapEventController.clearMapEvent(mapEvent.type);
      }
      this.emit("clearLayerEvent", mapEvent);
    } catch (error) {
      if (error instanceof Error) {
        const errorMsg: string = error.message;
        this.__throwError__("LayerController=>clearLayerEvent", errorMsg);
      } else {
        console.error("An unknown error occurred");
      }
    }
  }

  /**
   * 添加图片
   * @param {object[]} iamges
   * @param {string} images.name 
   * @param {string} images.url
   */
  public addImages(images: {name: string, url: string}[]) {
    if (Array.isArray(images)) {
      const imagePromises = images.map((item) => {
        return new Promise((resolve, reject) => {
          if (this.map.hasImage(item.name)) {
            console.warn(`iamge添加失败,${item.name}已经存在`);
            return resolve(item);
          } else {
            this.map.loadImage(item.url, ((err: any, image: any) => {
              if (err) {
                reject(err);
                this.__throwError__("LayerController => addImage", err);
              } else {
                this.map.addImage(item.name, image);
                resolve(image);
                this.emit("addImages", images);
              }
            }))
          }
        })
      })
      return Promise.all(imagePromises);
    } else {
      this.__throwError__("LayerController => addIamges", `入参错误， 请检查入参${images}`);
    }
  }

  /**
   * 移除图片
   * @param {string[]} imageNames
   */
  public removeImages(imageNames: string[]) {
    if (Array.isArray(imageNames)) {
      imageNames.forEach((iamgeName) => {
        this.map.removeImage(iamgeName);
        this.emit("removeImages", iamgeName);
      })
    } else {
      this.__throwError__("LayerController", `入参错误，请检查入参${imageNames}`);
    }
  }
}
